package com.knowswift.security.provider;

import com.knowswift.common.common.GlobalProperty;
import com.knowswift.common.utils.JwtTokenUtils;
import com.knowswift.security.AuthUserDetails;
import com.knowswift.security.AuthUserDetailsService;
import com.knowswift.security.account.User;
import com.knowswift.security.token.JwtAuthenticationToken;
import io.jsonwebtoken.JwtException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.StringUtils;

/**
 * @company https://www.knowswift.com
 */
public class JwtAuthenticationProvider extends AbstractMatchClassAuthenticationProvider {

    public JwtAuthenticationProvider(AuthUserDetailsService userDetailsService, Class<? extends JwtAuthenticationToken> matchClass) {
        super(userDetailsService, matchClass);
        this.userDetailsService = userDetailsService;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) authentication;
        String token = jwtAuthenticationToken.getToken();
        boolean visitor = jwtAuthenticationToken.isVisitor();
        if (visitor) {
            User user = new User();
            user.setRole("ROLE_VISITOR");
            return new JwtAuthenticationToken(user, token, GlobalProperty.APP, user.getAuthorities());
        }
        if (!StringUtils.hasText(token)) {
            throw new InsufficientAuthenticationException("尚未登录");
        }
        String platform = jwtAuthenticationToken.getPlatform();
        AuthUserDetails authUserDetails;
        try {
            String username = JwtTokenUtils.getUsernameFromToken(token);
            authUserDetails = userDetailsService.loadUserById(username);
            checkAuthUserDetails(authUserDetails);
            String key = platform.equals(GlobalProperty.ADMIN) ? "adminTokenVersion" : "appTokenVersion";
            JwtTokenUtils.validateToken(token, authUserDetails.getId(), authUserDetails.getTokenVersionMap().get(key));
        } catch (JwtException e) {
            throw new BadCredentialsException(e.getMessage(), null);
        }
        return new JwtAuthenticationToken(authUserDetails, token, platform, authUserDetails.getAuthorities());
    }
}
